package com.binfei.yjs.server.model.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;


/**
 * @param <T> 数据对象
 *            API接口统一返回载体
 */
@Slf4j
@Data
//@Schema(name = "ApiBaseDTO", description = "API接口返回对象")
public class ApiBaseDTO<T> implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 响应码
     * 小于1算是吧，大于1算成功，0是缺失情况，也代表失败
     */
    @Schema(description = "返回代码(大于或等于1时成功)")
    private int code;

    /**
     * 响应消息
     */
    @Schema(description = "返回信息说明")
    private String msg;

    /**
     * 响应扩展消息
     */
    @Schema(description = "扩展信息")
    private String extra;

    /**
     * 是否成功
     */
    @Schema(description = "请求操作是否成功")
    private boolean success;

    /**
     * 响应时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
//    @Builder.Default
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @Schema(description = "响应时间")
    private LocalDateTime time = LocalDateTime.now();

    /**
     * 响应数据
     */
    @Schema(description = "返回数据")
    private T data;


    /**
     * @param annApiCode 状态码
     * @param msg        提示消息
     * @param <T>        返回数据类型
     * @return 接口成功 自定义状态码+提示信息
     */
    public static <T> ApiBaseDTO<T> success(int annApiCode, String msg) {
        ApiBaseDTO<T> apiBaseDTO = new ApiBaseDTO<>();
        apiBaseDTO.setMsg(msg);
        apiBaseDTO.setCode(annApiCode);
        apiBaseDTO.setSuccess(true);
        return apiBaseDTO;
    }

    /**
     * @param msg 提示消息
     * @param <T> 返回数据类型
     * @return 接口成功 自定义提示信息
     */
    public static <T> ApiBaseDTO<T> success(String msg) {
        ApiBaseDTO<T> apiBaseDTO = new ApiBaseDTO<>();
        apiBaseDTO.setMsg(msg);
        apiBaseDTO.setCode(1);
        apiBaseDTO.setSuccess(true);
        return apiBaseDTO;
    }

    /**
     * @param <T> 返回数据类型
     * @return 接口成功
     */
    public static <T> ApiBaseDTO<T> success() {
        ApiBaseDTO<T> apiBaseDTO = new ApiBaseDTO<>();
        apiBaseDTO.setMsg("请求成功");
        apiBaseDTO.setCode(1);
        apiBaseDTO.setSuccess(true);
        return apiBaseDTO;
    }

    /**
     * @param annApiCode 状态码
     * @param msg        提示消息
     * @param data       返回数据
     * @param <T>        返回数据类型
     * @return 接口成功 自定义状态码+提示信息+数据
     */
    public static <T> ApiBaseDTO<T> success(int annApiCode, String msg, T data) {
        ApiBaseDTO<T> apiBaseDTO = new ApiBaseDTO<>();
        apiBaseDTO.setMsg(msg);
        apiBaseDTO.setCode(annApiCode);
        apiBaseDTO.setData(data);
        apiBaseDTO.setSuccess(true);
        return apiBaseDTO;
    }

    /**
     * @param msg  提示消息
     * @param data 返回数据
     * @param <T>  返回数据类型
     * @return 接口成功 自定义提示信息+数据
     */
    public static <T> ApiBaseDTO<T> success(String msg, T data) {
        ApiBaseDTO<T> apiBaseDTO = new ApiBaseDTO<>();
        apiBaseDTO.setMsg(msg);
        apiBaseDTO.setCode(1);
        apiBaseDTO.setData(data);
        apiBaseDTO.setSuccess(true);
        return apiBaseDTO;
    }


    /**
     * @param data 返回数据
     * @param <T>  返回数据类型
     * @return 接口成功 自定义提示信息+数据
     */
    public static <T> ApiBaseDTO<T> success(T data) {
        ApiBaseDTO<T> apiBaseDTO = new ApiBaseDTO<>();
        apiBaseDTO.setMsg("请求成功");
        apiBaseDTO.setCode(1);
        apiBaseDTO.setData(data);
        apiBaseDTO.setSuccess(true);
        return apiBaseDTO;
    }

    /**
     * @param msg  提示消息
     * @param data 返回数据
     * @param <T>  返回数据类型
     * @return 接口失败 自定义状态码+提示信息+数据
     */
    public static <T> ApiBaseDTO<T> error(int annApiCode, String msg, T data) {
        ApiBaseDTO<T> apiBaseDTO = new ApiBaseDTO<>();
        apiBaseDTO.setMsg(msg);
        apiBaseDTO.setCode(annApiCode);
        apiBaseDTO.setData(data);
        apiBaseDTO.setSuccess(false);
        return apiBaseDTO;
    }

    /**
     * @param msg 提示消息
     * @param <T> 返回数据类型
     * @return 接口失败 自定义状态码+提示信息
     */
    public static <T> ApiBaseDTO<T> error(int annApiCode, String msg) {
        ApiBaseDTO<T> apiBaseDTO = new ApiBaseDTO<>();
        apiBaseDTO.setMsg(msg);
        apiBaseDTO.setCode(annApiCode);
        apiBaseDTO.setSuccess(false);
        return apiBaseDTO;
    }


    /**
     * @param msg 提示消息
     * @param <T> 返回数据类型
     * @return 接口失败 自定义提示信息
     */
    public static <T> ApiBaseDTO<T> error(String msg) {
        ApiBaseDTO<T> apiBaseDTO = new ApiBaseDTO<>();
        apiBaseDTO.setMsg(msg);
        apiBaseDTO.setCode(-2);
        apiBaseDTO.setSuccess(false);
        return apiBaseDTO;
    }

    /**
     * @param <T> 返回数据类型
     * @return 接口失败 自定义提示信息
     */
    public static <T> ApiBaseDTO<T> error() {
        ApiBaseDTO<T> apiBaseDTO = new ApiBaseDTO<>();
        apiBaseDTO.setMsg("未知异常");
        apiBaseDTO.setCode(-2);
        apiBaseDTO.setSuccess(false);
        return apiBaseDTO;
    }

}